package cc.facesign.acl.controller;


import cc.facesign.acl.bean.AclMenu;
import cc.facesign.acl.bean.AclRole;
import cc.facesign.acl.bean.AclRoleMenu;
import cc.facesign.acl.bean.MenuTree;
import cc.facesign.acl.bean.vo.RoleEditVo;
import cc.facesign.acl.bean.vo.RoleVo;
import cc.facesign.acl.bean.vo.client.DeptVo;
import cc.facesign.acl.service.*;
import cc.facesign.acl.utils.GaineUtils;
import cc.facesign.common.exception.FacesignException;
import cc.facesign.common.utils.bean.R;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 权限角色 前端控制器
 * </p>
 *
 * @author acdongla
 * @since 2022-05-02
 */
@RestController
@RequestMapping("/acl/role")
@Api(description = "角色")
public class AclRoleController {

    @Autowired
    private AclRoleService roleService;

    @Autowired
    private AclMenuService menuService;

    @Autowired
    private GaineUtils gaineUtils;

    @Autowired
    private AclRoleMenuService roleMenuService;

    @Autowired
    private TblUserService userService;

    @Autowired
    private DeptService deptService;


    /**
     * 给角色批量分配菜单，不能跨单位操作
     * 存在的不会再次插入
     * @param menuIds menuId 集合
     * @return
     */
    @ApiOperation("给角色重新分配菜单")
    @PreAuthorize("hasAuthority('root')")
    @PostMapping("/addMenus/{roleId}")
    public R addMenus(@PathVariable String roleId, @RequestBody List<String> menuIds) {
        if (!gaineUtils.haveRole(roleId)) throw new FacesignException(R.ERROR, "角色权限异常");

        roleService.addMenuList(roleId, menuIds);

        return R.ok();
    }

    /**
     * 根据角色批量获取菜单列表，不能跨单位获取
     * @param roleIds 角色idList
     * @return
     */
    @ApiOperation("根据角色批量获取菜单列表")
    @GetMapping("/getMenusTree")
    public R getMenus(@RequestParam(required = false) List<String> roleIds) {
        if (roleIds == null || roleIds.size() == 0) return R.ok().data("data", new ArrayList<>());

        Set<String> roleSet = gaineUtils.roles();
        for (String roleId : roleIds) {
            if (!roleSet.contains(roleId)) throw new FacesignException(R.ERROR, "角色权限异常");
        }

        List<AclMenu> menuList = menuService.getByRoleIdBatch(roleIds);
        Set<AclMenu> set = new HashSet<>();
        for (AclMenu menu : menuList) {
            MenuTree tree = menuService.getMenuTreeByMenuId(menu.getId());
            List<AclMenu> list = menuService.getListByTree(tree);
            set.addAll(list);
        }

        return R.ok().data("data", set);
    }

    /**
     * 获取角色列表，不能跨单位获取
     * state为空，获取全部
     * state=1，停用的，state=0，正常的
     * @param state
     * @return
     */
    @ApiOperation("获取角色列表")
    @GetMapping("/getRoles")
    public R getRoles(@RequestParam(required = false) Integer state) {
        String userId = gaineUtils.getId();

        QueryWrapper<AclRole> w = new QueryWrapper<>();
        if (state != null) w.eq("status", state);

        if (!userId.equals("0")) {
            String rid = userService.getRid(userId);
            w.eq("rid", rid);
        }

        List<AclRole> roles = roleService.list(w);

        List<String> rids = roles.stream()
                .map(x -> x.getRid())
                .collect(Collectors.toList());

        List<DeptVo> depts = deptService.getInfoBatch(rids);

        return R.ok().data("roles", roles).data("depts", depts);
    }


    @ApiOperation("获取单个角色信息")
    @GetMapping("/getSingle/{roleId}")
    public R getSingle(@PathVariable String roleId) {
        if (!gaineUtils.haveRole(roleId)) {
            throw new FacesignException(R.ERROR, "角色权限异常");
        }

        AclRole role = roleService.getById(roleId);
        return R.ok().data("data", role);
    }

    /**
     * 新增角色，roleVo里包含菜单id
     * roleVo：
     *      menuIds： 菜单id
     *      rid：为空时默认为当前单位，否则为指定单位
     * @return
     */
    @ApiOperation("新增角色")
    @PreAuthorize("hasAuthority('root')")
    @PostMapping("/addRole")
    public R addRole(@RequestBody RoleVo vo) {
        String rid = vo.getRid();
        if (!StringUtils.isEmpty(rid) && !gaineUtils.haveRole(rid)) {
            throw new FacesignException(R.ERROR, "权限异常");
        }

        AclRole role = new AclRole();
        BeanUtils.copyProperties(vo, role);
        String id = UUID.randomUUID().toString().replaceAll("-","");
        role.setId(id);

        if (vo.getMenuIds() != null) {
            List<AclRoleMenu> list = new ArrayList<>();
            for (String menuId : vo.getMenuIds()) {
                list.add(new AclRoleMenu(id, menuId));
            }
            roleMenuService.relateBatch(list);
        }

        return R.ok();
    }

    @ApiOperation("编辑角色")
    @PreAuthorize("hasAuthority('root:update')")
    @PutMapping("/updateRole/{roleId}")
    public R updateRole(@PathVariable String roleId ,@RequestBody RoleEditVo vo) {
        if (!gaineUtils.haveRole(roleId)) {
            throw new FacesignException(R.ERROR, "角色权限异常");
        }

        AclRole role = roleService.getById(roleId);
        if (role == null) {
            return R.error();
        }

        BeanUtils.copyProperties(vo, role);

        roleService.updateById(role);

        return R.ok();
    }

    /**
     * 删除角色
     * @param roleId 角色id
     * @return
     */
    @ApiOperation("删除角色")
    @PreAuthorize("hasAuthority('root')")
    @DeleteMapping("/delete/{roleId}")
    public R delete(@PathVariable String roleId) {
        if (!gaineUtils.haveRole(roleId)) {
            throw new FacesignException(R.ERROR, "角色权限异常");
        }
        roleService.delete(roleId);

        return R.ok();
    }

    /**
     * 批量删除角色
     * @param roleIds 角色idList
     * @return
     */
    @ApiOperation("批量删除角色")
    @PreAuthorize("hasAuthority('root')")
    @DeleteMapping("/deleteBatch")
    public R deleteBatch(@RequestParam List<String> roleIds) {
        Set<String> roles = gaineUtils.roles();
        if (!roles.containsAll(roleIds)) {
            throw new FacesignException(R.ERROR, "角色权限异常");
        }

        for (String e : roleIds) {
            roleService.delete(e);
        }

        return R.ok();
    }

}

